/*
 * Copyright (c) 2010, Nikolaus Moll
 * All rights reserved.
 */
package net.miblounge.gradecalculator.core;

import net.miblounge.gradecalculator.core.descriptors.StudyRegulationsDescription;
import net.miblounge.gradecalculator.core.descriptors.courses.Course;
import net.miblounge.gradecalculator.core.descriptors.modulelistitems.IndividualModule;
import net.miblounge.gradecalculator.core.descriptors.modulelistitems.Module;
import net.miblounge.gradecalculator.core.descriptors.modulelistitems.SelectableModuleLists;
import net.miblounge.gradecalculator.core.descriptors.modulelists.ModuleList;
import net.miblounge.gradecalculator.core.interfaces.IModuleListItem;
import net.miblounge.gradecalculator.core.student.ExaminationResult;
import net.miblounge.gradecalculator.core.student.Student;
import net.miblounge.gradecalculator.core.student.StudentModule;


public final class AdaptedRegulationsUtil {
	private AdaptedRegulationsUtil()
	{
	}
	
	protected static void addModule(final AdaptedRegulations spo, final Module m, final Student student)
	{
		spo.addModule(new StudentModule(spo.getModules().size(), spo.getStudent(), m));
		for (Course c : m.getCourses()) {
			final ExaminationResult r = student.getResult(c.getExamNumber(), c.getIdentifier());	
			if (r == null) {
				continue;
			}
			
			spo.removeUnassignedResult(r);
		}
	}
	
	protected static void addModules(final AdaptedRegulations spo, final ModuleList moduleList, final Student student)
	{
		for (IModuleListItem listItem : moduleList.getModules()) {
			switch (listItem.getModuleType()) {
				case Module:
					// create module copy, auto increment sortOrder
					addModule(spo, ((Module)listItem).clone(), student);
					break;
				case IndividualModule:
					// create module copy, auto increment sortOrder
					final IndividualModule im = ((IndividualModule)listItem).clone();
					for (ExaminationResult result : student.getResults()) {
						if (result.getCourseDescription() == null) {
							continue;
						}
						
						if (!result.getCourseDescription().getModuleName().equals(im.getName())) {
							continue;
						}
						
						result.getCourseDescription().setParentModule(im);
						im.addCourse(result.getCourseDescription());
					}
					addModule(spo, im, student);
					break;
				case SelectableModuleLists:
					final SelectableModuleLists slm = (SelectableModuleLists)listItem;
					for (final ModuleList list : slm.getModuleLists()) {
						if (!student.hasSelected(list.getIdentifier())) {
							continue;
						}
						addModules(spo, list, student);
					}
					break;
				default:
					throw new IllegalArgumentException("Invalid module type");
			}
		}
	}
	
	// TODO: Add "free" results to an individual module...
	public static AdaptedRegulations createSPO(final StudyRegulationsDescription description, final Student student)
	{
		final AdaptedRegulations result = new AdaptedRegulations(student);
		result.setUnassignedResults(student.getResults());
		if (description != null) {
			addModules(result, description.getModuleList(), student);
		}
		return result;
	}
}
